import re
from turtle import width
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.pyplot import MultipleLocator, ylim
from mpl_toolkits.axes_grid1.inset_locator import mark_inset
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
import matplotlib.patches as patches
from matplotlib.patches import ConnectionPatch

colors=['darkorange','blue','deeppink','black','limegreen','green','teal']
#点标记的样式 ^表示三角形，*五角星，o圆点，3箭头
markers=['s-','o-','x-','d-','^-','p-','*-']
scale = [0, 1, 2.5, 5, 9]
figsize=[6,5]
dpi=300
fontsize=12
linewidth=2.7
markersize=12

def draw(workersList:list[int],filename:str):
    utilityDict = {}
    timeDict = {}
    memoryDict = {}
    responseDict = {}
    matchSizeDict = {}
    method = ''
    with open(filename, "r") as f:
        for item in f.readlines():
            items = item.split(" ")
            if method != items[0]:
                method = items[0]
                utilityDict.update({method: [float(items[1])]})
                timeDict.update({method: [float(items[2])]})
                memoryDict.update({method: [float(items[3])]})
                # responseDict.update({method:[float(items[4])]})
                matchSizeDict.update({method:[float(items[4])]})
            else:
                utilityDict[method].append(float(items[1]))
                timeDict[method].append(float(items[2]))
                memoryDict[method].append(float(items[3]))
                # responseDict[method].append(float(items[4]))
                matchSizeDict[method].append(float(items[4]))
    drawUtility(utilityDict,workersList)
    drawTime(timeDict,workersList)
    drawMemory(memoryDict,workersList)
    # drawResponse(responseDict,workersList)
    drawMatchSize(matchSizeDict,workersList)

def drawUtility(utilityDict:dict,idx:list[int]):
    plt.figure(figsize=(figsize[0], figsize[1]), dpi=dpi)
    # plt.rcParams['font.sans-serif'] = ['STSong']  # 显示汉字
    plt.xlabel('|$\it{W}$|', fontsize=fontsize+6)  # x轴标题
    plt.ylabel('Utility', fontsize=fontsize+6)  # y轴标题
    plt.tick_params(labelsize=fontsize)
    #自定义横坐标的刻度
    # scale = np.arange(len(idx))
    plt.xticks(scale, idx)

    ax = plt.gca()
    ax.ticklabel_format(style='sci', scilimits=(-1, 2), axis='y', useMathText=True)
    ax.get_yaxis().get_offset_text().set(va='bottom', ha='left')
    ax.yaxis.get_offset_text().set_fontsize(fontsize)
    # ax.yaxis.set_minor_locator(MultipleLocator(1))
    # ax.yaxis.set_major_locator(MultipleLocator(1))

    colorNum = 0
    itemName = []
    for item in utilityDict:
        itemName.append(item)
        plt.plot(scale,utilityDict[item], markers[colorNum], color=colors[colorNum], linewidth=linewidth, markersize=markersize,
                 markerfacecolor='none')
        colorNum += 1
    plt.legend(itemName)  # 设置折线名称

    # axins = inset_axes(ax, width="20%", height="20%", loc='lower left', #'upper right', 'upper left', 'lower left', 'lower right', 'right', 'center left', 'center right', 'lower center', 'upper center', 'center'
    #                bbox_to_anchor=(0.3, 0.45, 0.9,0.9),
    #                bbox_transform=ax.transAxes)
    # optdata = utilityDict[list(utilityDict.keys())[0]]
    # ftgoadata = utilityDict[list(utilityDict.keys())[-1]]
    # optdata1 = []
    # ftgoadata1 = []
    # for n in range(2,0,-1):
    #     optdata1.append(optdata[int(len(optdata)/2)+1]-n)
    # optdata1.append(optdata[int(len(optdata)/2)+1])
    # for n in range(1,3):
    #     optdata1.append(optdata[int(len(optdata)/2)+1]+n**3)
    # for n in range(2,0,-1):
    #     ftgoadata1.append(ftgoadata[int(len(ftgoadata)/2)+1]-n)
    # ftgoadata1.append(ftgoadata[int(len(ftgoadata)/2)+1])
    # for n in range(1,3):
    #     ftgoadata1.append(ftgoadata[int(len(ftgoadata)/2)+1]+n**3)
    # scatterMarker = ['s','o','x','d','^','p']
    # axins.xaxis.set_ticks(scale, idx)#修改子图刻度
    # axins.scatter(scale[3],optdata1[int(len(optdata)/2)+1],c="none",marker="s", edgecolors=colors[0])
    # axins.scatter(scale[3],ftgoadata1[int(len(optdata)/2)+1],c="none",marker="p", edgecolors=colors[-1])
    # axins.plot(scale,optdata1,markers[0],color=colors[0],linewidth=linewidth*0.8,markersize=markersize*0,markerfacecolor='none')
    # axins.plot(scale,ftgoadata1,markers[-1],color=colors[-1],linewidth=linewidth*0.8,markersize=markersize*0,markerfacecolor='none')
    # axins.xaxis.set_ticks([scale[3]])#仅仅显示对应的刻度
    # t1 = 0
    # for t in axins.xaxis.get_ticklabels()[::1]:#隐藏刻度值
    #     if t1 == 2:
    #         t1 +=1
    #         continue
    #     t1 +=1
    #     t.set_visible(False)
    #     t.set_ticks([])
    # # 设置放大区间
    # zone_left = 2
    # zone_right = 3

    # # 坐标轴的扩展比例（根据实际数据调整）
    # x_ratio = 0 # x轴显示范围的扩展比例
    # y_ratio = 0.9 # y轴显示范围的扩展比例
    # # X轴的显示范围
    # xlim0 = scale[zone_left]-(scale[zone_right]-scale[zone_left])*x_ratio
    # xlim1 = scale[zone_right]+(scale[zone_right]-scale[zone_left])*x_ratio
    # # Y轴的显示范围
    # y = np.hstack((optdata[zone_left:zone_right], ftgoadata[zone_left:zone_right]))
    # ylim0 = np.min(y)-(np.max(y)-np.min(y))*y_ratio
    # ylim1 = np.max(y)+(np.max(y)-np.min(y))*y_ratio
    # # ylim0 = optdata[zone_left]
    # # ylim1 = ftgoadata[zone_left]

    # # 调整子坐标系的显示范围
    # axins.set_xlim(xlim0, xlim1)
    # axins.set_ylim(ylim0, ylim1)
    # axins.set_ylim(ftgoadata[3]-2,optdata[3]+2)
    # axins.tick_params(labelsize=fontsize*0.6)
    #先在原图画一个框
    # xl = 0.3
    # yl = 400
    # sx = [scale[3]-xl,scale[3]+xl,scale[3]+xl,scale[3]-xl,scale[3]-xl]
    # sy = [optdata[3]-yl,optdata[3]-yl,optdata[3]+yl,optdata[3]+yl,optdata[3]-yl]
    # ax.plot(sx,sy,"black",linewidth=linewidth*0.3)
    # rect=patches.Rectangle((scale[3]-0.4, optdata[3]-400),0.6,800,linewidth=1,edgecolor='black',facecolor='none')#class matplotlib.patches.Rectangle(xy, width, height, angle=0.0, **kwargs)
    # ax.add_patch(rect)
    # 画两条线
    # xy = (scale[3]-xl,optdata[3]-yl)#主图点
    # xy2 = (axins.get_xlim()[0],axins.get_ylim()[0])#子图点 axins.get_ylim() 获取y轴的范围
    # xyA是子图里面的点，xyB是主图里面的点，coordsA和coordsB默认值"data"，也不用改，然后就是axesA要添加子图，axesB为要连接的主图
    # con = ConnectionPatch(xyA=xy2,xyB=xy,coordsA="data",coordsB="data",
    #     axesA=axins,axesB=ax,linewidth=linewidth*0.3)
    # axins.add_artist(con)

    # xy = (scale[3]+xl,optdata[3]+yl)
    # xy2 = (axins.get_xlim()[1],axins.get_ylim()[1])
    # con = ConnectionPatch(xyA=xy2,xyB=xy,coordsA="data",coordsB="data",
    #     axesA=axins,axesB=ax,linewidth=linewidth*0.3)
    # axins.add_artist(con)
    # plt.show()
    plt.savefig("picture/workerUtility.png")
    plt.close()

    #计算不同方法倍数关系
    print("Utility")
    multiple = {}
    for j in utilityDict:
        if j !='OPT':
            temp=0
            nu = 0
            for k in utilityDict[j]:
                temp += k
                nu+=1
            temp = temp/nu
            multiple.update({j:temp})
    print(multiple)
    ETGOA = multiple["DQL(ours)"]
    for item in multiple:
        # print(multiple[item])
        re = (ETGOA-multiple[item])/multiple[item]
        re = re*100
        print("DQL(ours) up",item,":\t",str(round(re,2)))

def drawTime(timeDict:dict,idx:list[int]):
    plt.figure(figsize=(figsize[0], figsize[1]), dpi=dpi)
    # plt.rcParams['font.sans-serif'] = ['STSong']  # 显示汉字
    plt.xlabel('|$\it{W}$|', fontsize=fontsize+6)  # x轴标题
    plt.ylabel('Time(secs)', fontsize=fontsize+6)  # y轴标题
    plt.tick_params(labelsize=fontsize)
    # 自定义横坐标的刻度
    # scale = np.arange(len(idx))
    plt.xticks(scale, idx)
    plt.yticks(rotation=60)

    # ax = plt.gca()
    # ax.ticklabel_format(style='sci', scilimits=(-1, 2), axis='y', useMathText=True)
    # ax.get_yaxis().get_offset_text().set(va='bottom', ha='left')
    # ax.yaxis.get_offset_text().set_fontsize(fontsize)

    colorNum = 0
    itemName = []
    for item in timeDict:
        if item == 'OPT':
            colorNum+=1
            continue
        itemName.append(item)
        plt.plot(scale, timeDict[item], markers[colorNum], color=colors[colorNum], linewidth=linewidth,
                 markersize=markersize,
                 markerfacecolor='none')
        colorNum += 1
    plt.legend(itemName)  # 设置折线名称
    # plt.show()
    plt.savefig("picture/workerTime.png")
    plt.close()
    #计算不同方法倍数关系
    print("Time")
    multiple = {}
    for j in timeDict:
        if j !='OPT':
            temp=0
            nu = 0
            for k in timeDict[j]:
                temp += k
                nu+=1
            temp = temp/nu
            multiple.update({j:temp})
    print(multiple)
    ETGOA = multiple["DQL(ours)"]
    for item in multiple:
        re = (multiple[item]-ETGOA)/ETGOA
        # re = re*100
        print("DQL(ours) up",item,":\t",str(round(re,2)))

def drawMemory(memoryDict:dict,idx:list[int]):
    plt.figure(figsize=(figsize[0], figsize[1]), dpi=dpi)
    # plt.rcParams['font.sans-serif'] = ['STSong']  # 显示汉字
    plt.xlabel('|$\it{W}$|', fontsize=fontsize+6)  # x轴标题
    plt.ylabel('Memory(KB)', fontsize=fontsize+6)  # y轴标题
    plt.tick_params(labelsize=fontsize)
    # 自定义横坐标的刻度
    # scale = np.arange(len(idx))
    plt.xticks(scale, idx)
    plt.yticks(rotation=60)

    ax = plt.gca()
    ax.ticklabel_format(style='sci', scilimits=(-1, 2), axis='y', useMathText=True)
    ax.get_yaxis().get_offset_text().set(va='bottom', ha='left')
    ax.yaxis.get_offset_text().set_fontsize(fontsize)

    colorNum = 0
    itemName = []
    for item in memoryDict:
        if item == 'OPT':
            colorNum += 1
            continue
        itemName.append(item)
        plt.plot(scale, memoryDict[item], markers[colorNum], color=colors[colorNum], linewidth=linewidth,
                 markersize=markersize,
                 markerfacecolor='none')
        colorNum += 1
    plt.legend(itemName)  # 设置折线名称
    # plt.show()
    plt.savefig("picture/workerMemory.png")
    plt.close()
    #计算不同方法倍数关系
    print("Momery")
    multiple = {}
    for j in memoryDict:
        if j !='OPT':
            temp=0
            nu = 0
            for k in memoryDict[j]:
                temp += k
                nu+=1
            temp = temp/nu
            multiple.update({j:temp})
    print(multiple)
    BGOA = multiple["DQL(ours)"]
    for item in multiple:
        re = (multiple[item]-BGOA)/multiple[item]
        print("DQL(ours) down",item,":\t",str(round(re*100,2)),"%")

def drawResponse(responseDict:dict,idx:list[int]):
    plt.figure(figsize=(figsize[0], figsize[1]), dpi=dpi)
    # plt.rcParams['font.sans-serif'] = ['STSong']  # 显示汉字
    plt.xlabel('|$\it{W}$|', fontsize=fontsize+6)  # x轴标题
    plt.ylabel('ARRTT(secs)', fontsize=fontsize+6)  # y轴标题  Average Real Response Time of Tasks
    plt.tick_params(labelsize=fontsize)
    # 自定义横坐标的刻度
    # scale = np.arange(len(idx))
    plt.xticks(scale, idx)
    plt.yticks(rotation=60)

    ax = plt.gca()
    ax.ticklabel_format(style='sci', scilimits=(-1, 2), axis='y', useMathText=True)
    ax.get_yaxis().get_offset_text().set(va='bottom', ha='left')
    ax.yaxis.get_offset_text().set_fontsize(fontsize)

    colorNum = 0
    itemName = []
    for item in responseDict:
        if item == 'OPT':
            colorNum += 1
            continue
        itemName.append(item)
        plt.plot(scale, responseDict[item], markers[colorNum], color=colors[colorNum], linewidth=linewidth,
                 markersize=markersize,
                 markerfacecolor='none')
        colorNum += 1
    plt.legend(itemName)  # 设置折线名称
    # plt.show()
    plt.savefig("picture/workerResponse.png")
    plt.close()
    #计算不同方法倍数关系
    print("Response")
    multiple = {}
    for j in responseDict:
        if j !='OPT':
            temp=0
            nu = 0
            for k in responseDict[j]:
                temp += k
                nu+=1
            temp = temp/nu
            multiple.update({j:temp})
    print(multiple)
    BGOA = multiple["DQL(ours)"]
    for item in multiple:
        re = multiple[item]/BGOA
        print("DQL(ours) up",item,":\t",str(round(re,2)))

def drawMatchSize(matchSizeDict:dict,idx:list[int]):
    plt.figure(figsize=(figsize[0], figsize[1]), dpi=dpi)
    # plt.rcParams['font.sans-serif'] = ['STSong']  # 显示汉字
    plt.xlabel('|$\it{W}$|', fontsize=fontsize+6)  # x轴标题
    plt.ylabel('Matching Size', fontsize=fontsize+6)  # y轴标题  
    plt.tick_params(labelsize=fontsize)
    # 自定义横坐标的刻度
    # scale = np.arange(len(idx))
    plt.xticks(scale, idx)

    ax = plt.gca()
    ax.ticklabel_format(style='sci', scilimits=(-1, 2), axis='y', useMathText=True)
    ax.get_yaxis().get_offset_text().set(va='bottom', ha='left')
    ax.yaxis.get_offset_text().set_fontsize(fontsize)

    colorNum = 0
    itemName = []
    for item in matchSizeDict:
        # if item == 'OPT':
        #     colorNum += 1
        #     continue
        itemName.append(item)
        plt.plot(scale, matchSizeDict[item], markers[colorNum], color=colors[colorNum], linewidth=linewidth,
                 markersize=markersize,
                 markerfacecolor='none')
        colorNum += 1
    plt.legend(itemName)  # 设置折线名称
    # plt.show()
    plt.savefig("picture/workerMatchSize.png")
    plt.close()

if __name__ =='__main__':
    workersList=[100,200,500,1000,5000]
    draw(workersList, "data/varyworkers.txt")